package com.hdax.dm.user.service.impl;

import cn.hutool.crypto.asymmetric.RSA;
import com.aliyun.dysmsapi20170525.*;
import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.models.*;
import com.aliyun.teautil.models.RuntimeOptions;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdax.dm.common.code.CodeEnum;
import com.hdax.dm.common.exception.DmException;
import com.hdax.dm.entity.base.Image;
import com.hdax.dm.entity.user.User;
import com.hdax.dm.token.TokenUtil;
import com.hdax.dm.user.dto.PersoninfoDto;
import com.hdax.dm.user.dto.UserDto;
import com.hdax.dm.user.feign.ImageFeign;
import com.hdax.dm.user.mappers.UserLoginMapper;
import com.hdax.dm.user.service.UserLoginService;
import com.hdax.dm.user.service.UserService;
import com.hdax.dm.utils.CommonResponse;
import com.hdax.dm.utils.ResponseUtil;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, User> implements UserLoginService {

    /**
     * 专门用于java程序去操作redis中的string
     * 所有的缓存记录都已键值对形式存在的
     * StringRedisTemplate这个是用来操作Map<String,String>类型的了
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ImageFeign imageFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private TokenUtil tokenUtil;

//    @Value("${jwt.rsa_private_key}")
//    private String rsa_private_key;
//
//    @Value("${jwt.rsa_public_key}")
//    private String rsa_public_key;

    @Override
    public CommonResponse msg(Map<String, String> params) throws DmException {
        String phone=params.get("phone");//手机号

        //option操作,选项的意思
        //opsForValue这个是操作字符串的
        Object value=stringRedisTemplate.opsForValue().get(phone+"_vcode");
        if (value!=null){
            //60s中不能重复获取
            throw new DmException(CodeEnum.USER_VCODE_WITHOUT_TIMEUUT);
        }
        //生成四位随机数
        String num="0123465789";
        //
        StringBuffer vcode=new StringBuffer();
        for (int i = 1; i <= 4; i++) {
            char n=num.charAt((int)(Math.random() * num.length()));
            vcode.append(n);
        }
        //存储数据,并设置时间
        stringRedisTemplate.opsForValue().set(phone+"_vcode",vcode.toString(),60, TimeUnit.SECONDS);

//        try {
//            //rabbitmq 消息队列中间件
//            Config config = new Config()
//                    // 您的 AccessKey ID
//                    .setAccessKeyId("LTAI4Fi6Dyp85rtARLMG1WoB")
//                    // 您的 AccessKey Secret
//                    .setAccessKeySecret("3qu7gkF1ZQqJ8bh4lWMgLewUkq48ks");
//            Client client = null;
//            client = new Client(config);
//            SendSmsRequest sendSmsRequest = new SendSmsRequest()
//                    .setPhoneNumbers(phone)
//                    .setSignName("邯郸翱翔")
//                    .setTemplateCode("SMS_180346654")
//                    .setTemplateParam("{\"code\":\""+vcode.toString()+"\"}");
//            RuntimeOptions runtime = new RuntimeOptions();
//            client.sendSmsWithOptions(sendSmsRequest, runtime);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        Map<String,String> map=new HashMap<>();
        map.put("phone",phone);
        map.put("vcode",vcode.toString());
        //发送消息到mq
        //直接模式  默认交换器 exchange=""
        //队列名称认为是交换器名称
        //rabbitTemplate.convertAndSend("dmsms",map);
        return ResponseUtil.returnSuccess(vcode.toString());
    }

    @Override
    public CommonResponse<UserDto> Smslogin(Map<String, String> params) throws DmException {
        UserDto userDto=null;

        String phone =params.get("phone");//手机号
        String vcode =params.get("vcode");//获取的验证码
        String redisKey=phone+"_vcode";
        //根究键获取值    redis存储的是真实有效的验证码
        String code=stringRedisTemplate.opsForValue().get(redisKey);
        //验证码得不到的情况
        if (code== null){
            //错误提示
            throw new DmException(CodeEnum.USER_VCODE_NOT_EXISTS);
        }
        //当输入的验证码与获取的验证码不一致时
        if (vcode==null || !vcode.equals(code)){
            //错误提示
            throw new DmException(CodeEnum.USER_VCODE_INVALID);
        }
        //正常情况下
        if (vcode.equals(code)){
            //数据库查询用户
            User user =userService.user(phone);
            Map<String,String> tokenParams = new HashMap<>();
            tokenParams.put("nickName",user.getNickName());
            tokenParams.put("phone",user.getPhone());
            tokenParams.put("realName",user.getRealName());
            tokenParams.put("id",user.getId().toString());
            String token = tokenUtil.createToken(tokenParams);
            //存储token到redis，过期时间为4h
            stringRedisTemplate.opsForValue().set("token:user:"+user.getId(),token, 4,TimeUnit.HOURS);

            userDto=new UserDto();
            userDto.setToken(token);
            userDto.setUserId(user.getId());
            userDto.setNickName(user.getNickName());
            userDto.setRealName(user.getRealName());
            userDto.setPhone(phone);
        }
        return ResponseUtil.returnSuccess(userDto);
    }

    /**
     * 手机号密码登录
     * @param params
     * @return
     * @throws DmException
     */
    @Override
    public CommonResponse Userlogin(Map<String, String> params) throws DmException {

        //获取手机号
        String phone=params.get("phone");
        //获取密码
        String password=params.get("password");
        //把密码进行MD5加密
        password= DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));

        //判断是否有该手机号的信息
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        queryWrapper.eq("password",password);
        User user=baseMapper.selectOne(queryWrapper);
        if (user==null){
            //抛出异常,表示手机号或密码不正确
            throw new DmException(CodeEnum.USER_VCODE_NOT_INCORRETONE);
        }else{
            UserDto userDto=null;
            //登录成功
            System.out.println("登录成功");
            //数据库查询用户
            User user1 =userService.user(phone);
            Map<String,String> tokenParams = new HashMap<>();
            tokenParams.put("nickName",user1.getNickName());
            tokenParams.put("phone",user1.getPhone());
            tokenParams.put("realName",user1.getRealName());
            tokenParams.put("id",user1.getId().toString());
            String token = tokenUtil.createToken(tokenParams);
            //存储token到redis，过期时间为4h
            stringRedisTemplate.opsForValue().set("token:user:"+user1.getId(),token, 4,TimeUnit.HOURS);

            userDto=new UserDto();
            userDto.setToken(token);
            userDto.setUserId(user1.getId());
            userDto.setNickName(user1.getNickName());
            userDto.setRealName(user1.getRealName());
            userDto.setPhone(phone);
            return ResponseUtil.returnSuccess(userDto);
        }
    }

    @Override
    public PersoninfoDto personinfo(Long userId) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("id",userId);
        User user = baseMapper.selectOne(userQueryWrapper);
        PersoninfoDto personinfo = PersoninfoDto.builder()
                .nickName(user.getNickName())
                .phone(user.getPhone())
                .realName(user.getRealName())
                .sex(user.getSex())
                .idCard(user.getIdCard())
                .birthday(user.getBirthday())
                .headUrl("https://img1.baidu.com/it/u=3718911818,375876443&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1663002000&t=b678899a107ec4906f66aae5a0142f9a")
                .interest(user.getHobby())
                .build();
        return personinfo;
    }
}
